package com.itheima.controller;


import com.itheima.domain.SysLog;
import com.itheima.domain.UserInfo;
import com.itheima.service.SysLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;


import javax.servlet.http.HttpServletRequest;

import java.lang.reflect.Method;
import java.util.Date;

@Component
@Aspect
public class LogAop {

    @Autowired
    private HttpServletRequest request;
    @Autowired
    private SysLogService sysLogService;

    private Date startTime;//开始访问时间
    private Class executionClass;//访问的类
    private Method executionMethod;//访问的方法

    //前置通知
    @Before("execution(* com.itheima.controller.*.*(..))")
    public void doBefore(JoinPoint jp) throws NoSuchMethodException {
        //当前访问时间
        startTime = new Date();
        //获取访问的类
        executionClass = jp.getTarget().getClass();
        //获取访问的方法
        String methodName = jp.getSignature().getName();//获取方法名称
        Object[] args = jp.getArgs();//获取访问方法的参数
        if(args==null && args.length==0){//无参数
            executionMethod = executionClass.getMethod(methodName);//获取没有参数的方法
        }
        else{
            //有参数，将所有参数元素遍历，获取对应的class,放进Class[]
            Class[] classArgs = new Class[args.length];
            for (int i = 0; i < args.length; i++) {
                classArgs[i]=args[i].getClass();
            }
            //获取有参数的方法
            executionMethod= executionClass.getMethod(methodName, classArgs);
        }
    }

    //后置通知
    @After("execution(* com.itheima.controller.*.*(..))")
    public void doAfter(JoinPoint jp) throws Exception{
        //获取访问时间
        Long executionTime = new Date().getTime()-startTime.getTime();

        //获取类上的@RequestMapping对象
        if(executionClass!=LogAop.class && executionClass!=null && executionMethod!=null){
            RequestMapping classAnnotation = (RequestMapping) executionClass.getAnnotation(RequestMapping.class);
            if(classAnnotation!=null){
                //获取方法上的@RequestMapping对象
                RequestMapping methodAnnotation = executionMethod.getAnnotation(RequestMapping.class);
                if(methodAnnotation!=null){
                    //url的值为：类路径+方法路径
                    String url ="";
                    url = classAnnotation.value()[0]+methodAnnotation.value()[0];
                    //获取ip
                    String ip = request.getRemoteAddr();
                    //获取操作者用户名，通过securityContext获取，也可通过request.getSession中获取
                    SecurityContext context = SecurityContextHolder.getContext();
                    //使用request.getSession获取操作者
                    //SecurityContext context = (SecurityContext) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
                    String username = ((User)context.getAuthentication().getPrincipal()).getUsername();

                    //将数据保存到数据库中
                    SysLog sysLog = new SysLog();
                    sysLog.setExecutionTime(executionTime);
                    sysLog.setUrl(url);
                    sysLog.setIp(ip);
                    sysLog.setVisitTime(startTime);
                    sysLog.setMethod("[类名]"+executionClass.getName()+"[方法名]"+executionMethod.getName());
                    sysLog.setUsername(username);

                    //将数据保存到数据库
                    sysLogService.save(sysLog);

                }
            }


        }

    }
}






